package com.yunfei.commonbase.generationcode.code;

import com.yunfei.commonbase.generationcode.database.Config;
import com.yunfei.commonbase.generationcode.database.DBCode;
import org.omg.CORBA.CODESET_INCOMPATIBLE;

import java.io.*;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;

public class CreateCode {

    /**
     * 单词首字母大写
     *
     * @param str
     * @return
     */
    public static String upperCase(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 数据库字段名所有单词首字母全大写
     */
    public static String uppCase(String keyStr) {
        String[] colStrs = keyStr.split("_");
        StringBuilder cameStr = new StringBuilder();
        for (String colStr : colStrs) {
            cameStr.append(CreateCode.upperCase(colStr));
        }
        return cameStr.toString();
    }

    /**
     * 驼峰命名
     */
    public static String camelCase(String keyStr) {
        String[] colStrs = keyStr.split("_");
        if (colStrs.length == 1) {
            return colStrs[0];
        } else {
            StringBuilder cameStr = new StringBuilder();
            for (int i = 0; i < colStrs.length; i++) {
                if (i == 0) {
                    cameStr = new StringBuilder(colStrs[0]);
                } else {
                    cameStr.append(CreateCode.upperCase(colStrs[i]));
                }
            }
            return cameStr.toString();
        }
    }
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append("_");
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
    /**
     * 检查文件夹是否存在 不存在则创建
     *
     * @param filePath
     */
    public void mkPath(File filePath) {
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
    }


    /**
     * 判断与数据库类型
     */
    public static String judgementType(String type) {
        if ("INT".equals(type)) {
            return "Integer";
        } else if ("NVARCHAR".equals(type)) {
            return "String";
        } else if ("VARCHAR".equals(type)) {
            return "String";
        } else if ("CHAR".equals(type)) {
            return "String";
        } else if ("BLOB".equals(type)) {
            return "byte[]";
        } else if ("TEXT".equals(type)) {
            return "String";
        } else if ("INTEGER".equals(type)) {
            return "Long";
        } else if ("TINYINT".equals(type)) {
            return "Integer";
        } else if ("SMALLINT".equals(type)) {
            return "Integer";
        } else if ("MEDIUMINT".equals(type)) {
            return "Integer";
        } else if ("BIT".equals(type)) {
            return "Boolean";
        } else if ("BIGINT".equals(type)) {
            return "Long";
        } else if ("FLOAT".equals(type)) {
            return "Float";
        } else if ("DOUBLE".equals(type)) {
            return "Double";
        } else if ("DECIMAL".equals(type)) {
            return "BigDecimal";
        } else if ("BOOLEAN".equals(type)) {
            return "Long";
        } else if ("ID".equals(type)) {
            return "Long";
        } else if ("DATE".equals(type)) {
            return "Date";
        } else if ("TIME".equals(type)) {
            return "Date";
        } else if ("DATETIME".equals(type)) {
            return "Date";
        } else if ("TIMESTAMP".equals(type)) {
            return "Date";
        } else if ("YEAR".equals(type)) {
            return "Date";
        }
        return "错误";
    }


    /**
     * 生成controller
     */
    public void mkController(Config config) {

        try {
            File file = new File(".");
            String[] paths = config.getSourcesPath().split("\\.");
            String filePaths = "";
            for (String path : paths) {
                filePaths = filePaths + path + "\\";
            }
            File filePathController = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\controller");
            mkPath(filePathController);

            String tableNameUp = CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Controller.java";
            File fileController = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\controller\\" + tableNameUp);

            fileController.delete();
            fileController.createNewFile();
            FileOutputStream fos = new FileOutputStream(fileController);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));

            bw.write("package " + config.getSourcesPath() + "." + camelCase(config.getDataBaseName()) + ".controller;");
            bw.newLine();
            bw.newLine();
            bw.write("import org.springframework.web.bind.annotation.RestController;");
            bw.newLine();
            bw.newLine();
            bw.write("@RestController");
            bw.newLine();
            bw.write("public class " + CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Controller {");
            bw.newLine();
            bw.newLine();
            bw.write("}");
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成mapper
     */
    public void mkMapper(Config config) {

        try {

            File file = new File(".");
            String[] paths = config.getSourcesPath().split("\\.");
            String filePaths = "";
            for (String path : paths) {
                filePaths = filePaths + path + "\\";
            }
            File filePathDao = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\mapper");
            mkPath(filePathDao);

            String tableDao = CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Mapper.java";
            File fileDao = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\mapper\\" + tableDao);


            fileDao.delete();
            fileDao.createNewFile();
            FileOutputStream fos = new FileOutputStream(fileDao);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
            bw.write("package " + config.getSourcesPath() + "." + camelCase(config.getDataBaseName()) + ".mapper;");
            bw.newLine();
            bw.newLine();

            bw.write("import com.yunfei.commonbase.base.BaseMapper;");
            bw.newLine();
            bw.write("import "+config.getSourcesPath()+"."+camelCase(config.getDataBaseName())+".entity."+upperCase(camelCase(config.getDataBaseName()))+";");
            bw.newLine();
            bw.write("import org.apache.ibatis.annotations.Mapper;");
            bw.newLine();
            bw.newLine();

            bw.write("@Mapper");
            bw.newLine();
            bw.write("public interface " + CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Mapper extends BaseMapper<"+CreateCode.upperCase(camelCase(config.getDataBaseName()))+"> {");
            bw.newLine();
            bw.newLine();

            bw.write("}");
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成xml
     */
    public void mkXML(Config config) {

        try {
            File file = new File(".");
            String[] paths = config.getSourcesPath().split("\\.");
            String filePaths = "";
            for (String path : paths) {
                filePaths = filePaths + path + "\\";
            }
            File filePathXml = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\mapper");
            mkPath(filePathXml);

            String tablexml = CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Mapper.xml";
            File filexml = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\mapper\\" + tablexml);
            String namespace = config.getSourcesPath() + "." + camelCase(config.getDataBaseName()) + ".mapper." + CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Mapper";

            filexml.delete();
            filexml.createNewFile();
            FileOutputStream fos = new FileOutputStream(filexml);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
            bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            bw.newLine();
            bw.write("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">");
            bw.newLine();
            bw.newLine();
            bw.write("<mapper namespace=\"" + namespace + "\"> ");
            bw.newLine();

            //sql字段
            bw.write("    <sql id=\"baseFields\">");
            bw.newLine();
            List<String> columnNames = DBCode.getColumnNames(config.getDataBaseName());
            for (int i = 0; i < columnNames.size(); i++) {
                String columnName = columnNames.get(i);
                if (i == 0) {
                    bw.write("        A." + columnName + " ");
                } else {
                    bw.write(" A." + columnName + " ");
                }

                String[] colStrs = columnName.split("_");
                StringBuilder uppCaseStr = new StringBuilder();
                for (int j = 0; j < colStrs.length; j++) {
                    if (colStrs.length == 1) {
                        uppCaseStr = new StringBuilder(colStrs[0]);
                    } else {
                        if (j == 0) {
                            uppCaseStr = new StringBuilder(colStrs[0]);
                        } else {
                            uppCaseStr.append(CreateCode.upperCase(colStrs[j]));
                        }
                    }
                }
                if (i == columnNames.size() - 1) {
                    bw.write(uppCaseStr.toString());
                } else {
                    bw.write(uppCaseStr + ", ");
                }

            }

            bw.newLine();
            bw.write("    </sql>");
            bw.newLine();
            bw.newLine();



            bw.write("</mapper> ");
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成entity
     */
    public void mkEntity(Config config) {

        try {
            File file = new File(".");
            String[] paths = config.getSourcesPath().split("\\.");
            StringBuilder filePaths = new StringBuilder();
            for (String path : paths) {
                filePaths.append(path).append("\\");
            }
            File filePathEntity = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\entity");
            mkPath(filePathEntity);

            String tableEntity = CreateCode.upperCase(camelCase(config.getDataBaseName())) + ".java";
            File fileEntity = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\entity\\" + tableEntity);

            fileEntity.delete();
            fileEntity.createNewFile();
            FileOutputStream fos = new FileOutputStream(fileEntity);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
            bw.write("package " + config.getSourcesPath() + "." + camelCase(config.getDataBaseName()) + ".entity;");
            bw.newLine();
            bw.newLine();
            bw.write("import com.yunfei.commonbase.annotation.Id;");
            bw.newLine();
            bw.write("import com.yunfei.commonbase.base.BaseEntity;");
            bw.newLine();
            bw.write("import java.util.Date;");
            bw.newLine();
            bw.newLine();
            bw.write("public class " + CreateCode.upperCase(camelCase(config.getDataBaseName())) + " extends BaseEntity{");
            bw.newLine();
            List<String> columnNames = DBCode.getColumnNames(config.getDataBaseName());
            List<String> columnTypes = DBCode.getColumnTypes(config.getDataBaseName());
            String primaryKeyCol=DBCode.getPrimaryKeyCol(config.getDataBaseName());
            for (int i = 0; i < columnTypes.size(); i++) {
                String type = CreateCode.judgementType(columnTypes.get(i));
                String camecase = CreateCode.camelCase(columnNames.get(i));
                if(columnNames.get(i).equals(primaryKeyCol)){
                    bw.write("    @Id ");
                    bw.write(" private " + type + " " + camecase + ";");
                }else{
                    bw.write("    private " + type + " " + camecase + ";");
                }
                bw.newLine();
            }
            bw.newLine();
            for (int i = 0; i < columnTypes.size(); i++) {
                String type = CreateCode.judgementType(columnTypes.get(i));
                String uppCase = CreateCode.uppCase(columnNames.get(i));
                String camelCase = CreateCode.camelCase(columnNames.get(i));
                bw.write("    public void set" + uppCase + "(" + type + " " + camelCase + "){");
                bw.newLine();
                bw.write("        this." + camelCase + "=" + camelCase + ";");
                bw.newLine();
                bw.write("    }");
                bw.newLine();
                bw.newLine();
                bw.write("    public " + type + " get" + uppCase + "( ){");
                bw.newLine();
                bw.write("        return " + camelCase + ";");
                bw.newLine();
                bw.write("    }");
                bw.newLine();
                bw.newLine();
            }

            bw.newLine();

            bw.write("");
            bw.write("}");
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成service
     */
    public void mkServie(Config config) {

        try {
            File file = new File(".");
            String[] paths = config.getSourcesPath().split("\\.");
            String filePaths = "";
            for (int i = 0; i < paths.length; i++) {
                filePaths = filePaths + paths[i] + "\\";
            }

            File filePathService = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\service");
            mkPath(filePathService);

            String tableService = CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Service.java";
            File fileService = new File(file.getCanonicalPath() + "\\src\\main\\java\\" + filePaths + camelCase(config.getDataBaseName()) + "\\service\\" + tableService);
            fileService.delete();
            fileService.createNewFile();

            FileOutputStream fos = new FileOutputStream(fileService);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
            bw.write("package " + config.getSourcesPath() + "." + camelCase(config.getDataBaseName()) + ".service;");
            bw.newLine();
            bw.newLine();
            bw.write("import com.yunfei.commonbase.base.BaseService;");
            bw.newLine();
            bw.write("import " + config.getSourcesPath() + "." + camelCase(config.getDataBaseName()) + ".mapper." + CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Mapper;");
            bw.newLine();
            bw.write("import "+config.getSourcesPath()+"."+camelCase(camelCase(config.getDataBaseName()))+".entity."+upperCase(camelCase(config.getDataBaseName()))+";");
            bw.newLine();
            bw.write("import org.springframework.stereotype.Service;");

            bw.newLine();
            bw.newLine();
            bw.write("@Service");
            bw.newLine();
            bw.write("public class " + CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Service extends  BaseService<"+CreateCode.upperCase(camelCase(config.getDataBaseName()))+"," + CreateCode.upperCase(camelCase(config.getDataBaseName())) + "Mapper > {");
            bw.newLine();
            bw.newLine();
            bw.newLine();
            bw.newLine();
            bw.write("}");
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
